classdef PrimaryPRNCode < PRNCode

properties
	NumberOfUpsampledSamples
	NumberOfPeriods;
end % end of properties

properties (SetAccess = protected)
	UpsampledCodesPeriod;
	UpsampledCodes;
	MatlabSavedCodesFileName;
end % end of properties

properties (SetAccess = protected, GetAccess = protected)
	generateCodes;
end

methods

% NumberOfUpsampledSamples: SecondaryPRNCode.ChipPeriod / sample.SamplingPeriod
	function obj = PrimaryPRNCode(Name, NumberOfUpsampledSamples, NumberOfPeriods)
		obj = obj@PRNCode(Name);
		obj.NumberOfUpsampledSamples = NumberOfUpsampledSamples;
		obj.NumberOfPeriods = NumberOfPeriods;
		switch (obj.Name)
			case 'E5aI'
				obj.CodesFileName = './E5aI_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E5aI_primary_codes.mat';
				obj.NumberOfChips = 10230;
				obj.ChipPeriod = 1e-3/obj.NumberOfChips;
			case 'E5aQ'
				obj.CodesFileName = './E5aQ_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E5aQ_primary_codes.mat';
				obj.NumberOfChips = 10230;
				obj.ChipPeriod = 1e-3/obj.NumberOfChips;
			case 'E5bI'
				obj.CodesFileName = './E5bI_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E5bI_primary_codes.mat';
				obj.NumberOfChips = 10230;
				obj.ChipPeriod = 1e-3/obj.NumberOfChips;
			case 'E5bQ'
				obj.CodesFileName = './E5bQ_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E5bQ_primary_codes.mat';
				obj.NumberOfChips = 10230;
				obj.ChipPeriod = 1e-3/obj.NumberOfChips;
			case 'E1b'
				obj.CodesFileName = './E1b_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E1b_primary_codes.mat';
				obj.NumberOfChips = 4092;
				obj.ChipPeriod = 4e-3/obj.NumberOfChips;
			case 'E1c'
				obj.CodesFileName = './E1c_primary_codes.txt';
				obj.MatlabSavedCodesFileName = './E1c_primary_codes.mat';
				obj.NumberOfChips = 4092;
				obj.ChipPeriod = 4e-3/obj.NumberOfChips;
			case 'B1'
				obj.MatlabSavedCodesFileName = './B1_primary_codes.mat';
				obj.NumberOfChips = 2046;
				obj.ChipPeriod = 1e-3/obj.NumberOfChips;
				obj.generateCodes = @obj.generateCodeB1;
			otherwise
				error('Unknown signal name');
		end

		try 
			load(obj.MatlabSavedCodesFileName, 'Codes');
			obj.Codes = Codes;
		catch exception
			if (strfind(obj.Name, 'E') > 0)
				obj.loadCodes();
			else
				obj.generateCodes();
			end
			Codes = obj.Codes;
			save(obj.MatlabSavedCodesFileName, 'Codes');
		end

		obj.resetUpsampledCodes();
	end

	function out = getCode(obj, SVID, TimeShift)
		index_double = mod(TimeShift/obj.UpsampledCodesPeriod,...
	 										 obj.NumberOfUpsampledSamples);
		if (index_double < 0)
			%index_double = obj.NumberOfUpsampledSamples - index_double;
			index_double = obj.NumberOfUpsampledSamples + index_double;
		end
		%index_integer = ceil(index_double);
		index_integer = floor(index_double);
		out = circshift(obj.UpsampledCodes(SVID, :).', index_integer).';
	end

end % end of methods

methods (Access = protected)

	function obj = resetUpsampledCodes(obj)
		[m n] = size(obj.Codes);
		n_new = obj.NumberOfUpsampledSamples;
		upsample_rate = n_new/n;
		obj.UpsampledCodes = zeros(m, n_new);
		obj.UpsampledCodes = obj.Codes(:, ceil((1:n_new)/upsample_rate));
		obj.UpsampledCodesPeriod = obj.ChipPeriod/upsample_rate;
	end

	function obj = generateCodeB1(obj)
		NumberOfSVs = 37;
		obj.Codes = zeros(NumberOfSVs, obj.NumberOfChips);
		polynom1 = [0 1 7 8 9 10 11];
		polynom2 = [0 1 2 3 4 5 8 9 11];
		lfsr1 = LFSR(polynom1); 
		lfsr1.InitialState = [0 1 0 1 0 1 0 1 0 1 0];
		lfsr1.Reset;
		g1 = lfsr1.Generate(obj.NumberOfChips);
		for SVID=1:NumberOfSVs
			fprintf(1, 'Generating B1 PRN code %d ...\n', SVID);
			switch (SVID)
				case 1
					polynom3 = [1 3];
				case 2
					polynom3 = [1 4];
				case 3
					polynom3 = [1 5];
				case 4
					polynom3 = [1 6];
				case 5
					polynom3 = [1 8];
				case 6
					polynom3 = [1 9];
				case 7
					polynom3 = [1 10];
				case 8
					polynom3 = [1 11];
				case 9
					polynom3 = [2 7];
				case 10
					polynom3 = [3 4];
				case 11
					polynom3 = [3 5];
				case 12
					polynom3 = [3 6];
				case 13
					polynom3 = [3 8];
				case 14
					polynom3 = [3 9];
				case 15
					polynom3 = [3 10];
				case 16
					polynom3 = [3 11];
				case 17
					polynom3 = [4 5];
				case 18
					polynom3 = [4 6];
				case 19
					polynom3 = [4 8];
				case 20
					polynom3 = [4 9];
				case 21
					polynom3 = [4 10];
				case 22
					polynom3 = [4 11];
				case 23
					polynom3 = [5 6];
				case 24
					polynom3 = [5 8];
				case 25
					polynom3 = [5 9];
				case 26
					polynom3 = [5 10];
				case 27
					polynom3 = [5 11];
				case 28
					polynom3 = [6 8];
				case 29
					polynom3 = [6 9];
				case 30
					polynom3 = [6 10];
				case 31
					polynom3 = [6 11];
				case 32
					polynom3 = [8 9];
				case 33
					polynom3 = [8 10];
				case 34
					polynom3 = [8 11];
				case 35
					polynom3 = [9 10];
				case 36
					polynom3 = [9 11];
				case 37
					polynom3 = [10 11];
				otherwise
					error('Unknown SVID')
			end
			lfsr2 = LFSR(polynom2);
			lfsr2.InitialState = [0 1 0 1 0 1 0 1 0 1 0];
			lfsr2.Reset;
			lfsr2.OutputCoefficients = polynom3;
			g2 = lfsr2.Generate(obj.NumberOfChips);
			obj.Codes(SVID, :) = mod(g1+g2, 2); 
			clear lfsr2;
		end
	end

end % end of methods

end % end of class
